package com.nchu.commondevelopmentframework.common.security.config;

import com.nchu.commondevelopmentframework.common.security.handler.AuthAccessDeniedHandler;
import com.nchu.commondevelopmentframework.common.security.handler.AuthEntryPointHandler;
import com.nchu.commondevelopmentframework.common.security.manager.MyAuthorizationManager;
import com.nchu.commondevelopmentframework.common.utils.JwtUtils;
import com.nchu.commondevelopmentframework.common.utils.SpringContextUtils;
import com.nchu.commondevelopmentframework.common.security.filter.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @className: SecurityConfig
 * @description: SpringSecurity配置类
 * @author: Li Chuanwei
 * @date: 2024/02/06 23:02
 * @Company: Copyright [日期] by [作者或个人]
 **/

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
    @Autowired
    private AuthEntryPointHandler authEntryPointHandler;

    @Autowired
    private AuthAccessDeniedHandler authAccessDeniedHandler;

    @Autowired
    private MyAuthorizationManager authorizationManager;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(authorizeRequests ->
                        authorizeRequests
                                // 允许访问的接口，比如登录接口和注册接口
                                .requestMatchers("/user/login").permitAll()
                                // 其他请求需要进行认证
                                .anyRequest().access(authorizationManager)
                );

        //禁用登录页面
        http.formLogin(AbstractHttpConfigurer::disable);
        //禁用登出页面
        http.logout(AbstractHttpConfigurer::disable);
        //禁用session
        http.sessionManagement(AbstractHttpConfigurer::disable);
        //禁用httpBasic
        http.httpBasic(AbstractHttpConfigurer::disable);
        //禁用csrf保护
        http.csrf(AbstractHttpConfigurer::disable);

        //通过上下文获取AuthenticationManager和JwtUtils
        AuthenticationManager authenticationManager = SpringContextUtils.getBean("authenticationManager");
        JwtUtils jwtUtils = SpringContextUtils.getBean("jwtUtils");
        //添加自定义token验证过滤器
        http.addFilterBefore(new JwtAuthenticationFilter(jwtUtils), UsernamePasswordAuthenticationFilter.class);

        //自定义处理器
        http.exceptionHandling(exceptionHandling -> exceptionHandling
                .accessDeniedHandler(authAccessDeniedHandler) //处理用户权限不足
                .authenticationEntryPoint(authEntryPointHandler) //处理用户未登录（未携带token）
        );

        return http.build();
    }

    /**
     * 密码编码器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 身份验证管理器
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }
}